#!/usr/bin/env python

import pygame
import types


class Event(object):
    pass

#------------------------------------------------------------------
# PYGAME EVENT WRAPPERS
#------------------------------------------------------------------

class PyGameQuit(object):
    __slots__ = []
    def __init__(self):
        pass

class PyGameActiveEvent(object):
    __slots__ = ['gain', 'state']
    def __init__(self, gain, state):
        self.gain = gain
        self.state = state

class PyGameKeyDown(object):
    __slots__ = ['unicode', 'key', 'mod']
    def __init__(self, unicode, key, mod):
        self.unicode = unicode
        self.key = key
        self.mod = mod
        
class PyGameKeyUp(object):
    __slots__ = ['key', 'mod']
    def __init__(self, key, mod):
        self.key = key
        self.mod = mod

class PyGameMouseMotion(object):
    __slots__ = ['pos', 'rel', 'buttons']
    def __init__(self, pos, rel, buttons):
        self.pos = pos
        self.rel = rel
        self.buttons = buttons

class PyGameMouseButtonUp(object):
    __slots__ = ['pos', 'button']
    def __init__(self, pos, button):
        self.pos = pos
        self.button = button
        
class PyGameMouseButtonDown(object):
    __slots__ = ['pos', 'button']
    def __init__(self, pos, button):
        self.pos = pos
        self.button = button

class PyGameJoyAxisMotion(object):
    __slots__ = ['joy', 'axis', 'value']
    def __init__(self, joy, axis, value):
        self.joy = joy
        self.axis = axis
        self.value = value
        
class PyGameJoyBallMotion(object):
    __slots__ = ['joy', 'ball', 'rel']
    def __init__(self, joy, ball, rel):
        self.joy = joy
        self.ball = ball
        self.rel = rel

class PyGameJoyHatMotion(object):
    __slots__ = ['joy', 'hat', 'value']
    def __init__(self, joy, hat, value):
        self.joy = joy
        self.hat = hat
        self.value = value
        
class PyGameJoyButtonUp(object):
    __slots__ = ['joy', 'button']
    def __init__(self, joy, button):
        self.joy = joy
        self.button = button

class PyGameJoyButtonDown(object):
    __slots__ = ['joy', 'button']
    def __init__(self, joy, button):
        self.joy = joy
        self.button = button
        
class PyGameMouseButtonDown(object):
    __slots__ = ['joy', 'button']
    def __init__(self, joy, button):
        self.joy = joy
        self.button = button

class PyGameVideoResize(object):
    __slots__ = ['size', 'w', 'h']
    def __init__(self, size, w, h):
        self.size = size
        self.w = w
        self.h = h

class PyGameVideoExpose(object):
    __slots__ = []
    def __init__(self):
        pass

#------------------------------------------------------------------
# EVENT MANAGER
#------------------------------------------------------------------
class EventManager(object):
    def __init__(self):
        self.listeners = { }
        self.qeue = ( [], [] )
        self.active = 0
    
    def register(self, event, listener):
        if not event in self.listeners:
            self.listeners[ event ] = []
        self.listeners[event].append( listener )
    
    def remove(self, event, listener):
        _type = type(event)
        try:
            del self.listeners[_type][ listener ]
        except Exception:
            pass
        
    def update(self, time):
        for event in pygame.event.get():
            self.dispatch( _translatePyGameEvent( event ) )
            
        #Clear event qeue
        index = self.active
        if not self.active: self.active = 1
        else: self.active = 0
        
        while self.qeue[index]:
            self._broadcast( self.qeue[index].pop() )
        
    def dispatch(self, event, immediate=False):
        if immediate:
            self._broadcast(event)
        else:
            self.qeue[ self.active ].append( event )

    
    def _broadcast(self, event):
        _type = type(event)
        try:
            for listener in self.listeners[_type]:
                self._send( event, listener )
        except KeyError:
            pass
    
    def _send( self, event, reciever ):
        if type(reciever) == types.MethodType or type( reciever ) == types.FunctionType:
            try:
                reciever( event )
            except Exception, e:
                print("Failed to send message %s" %( e ))
        elif type( reciever ) == types.ClassType:
            try:
                getattr( reciever, 'onEvent', lambda *_, **__: None )( event )
            except Exception, e:
                print("Could not send message %s" %e)

_manager = EventManager()


def _translatePyGameEvent( event ):
    if event.type == pygame.QUIT:
        return PyGameQuit()
    elif event.type == pygame.ACTIVEEVENT:
        return PyGameActiveEvent( event.gain, event.state )
    elif event.type == pygame.KEYDOWN:
        return PyGameKeyDown( event.unicode, event.key, event.mod )
    elif event.type == pygame.KEYUP:
        return PyGameKeyUp( event.key, event.mod )
    elif event.type == pygame.MOUSEMOTION:
        return PyGameMouseMotion( event.pos, event.rel, event.buttons )
    elif event.type == pygame.MOUSEBUTTONUP:
        return PyGameMouseButtonUp( event.pos, event.button )
    elif event.type == pygame.MOUSEBUTTONDOWN:
        return PyGameMouseButtonDown( event.pos, event.button )
    elif event.type == pygame.JOYAXISMOTION:
        return PyGameJoyAxisMotion( event.joy, event.axis, event.pos )
    elif event.type == pygame.JOYBALLMOTION:
        return PyGameJoyBallMotion( event.joy, event.ball, event.rel )
    elif event.type == pygame.JOYHATMOTION:
        return PyGameJoyHatMotion( event.joy, event.hat, event.value )
    elif event.type == pygame.JOYBUTTONUP:
        return PyGameJoyButtonUp( event.joy, event.button )
    elif event.type == pygame.JOYBUTTONDOWN:
        return PyGameJoyButtonDown( event.joy, event.button )
    elif event.type == pygame.VIDEORESIZE:
        return PyGameVideoResize( event.size, event.w, event.h )
    elif event.type == pygame.VIDEOEXPOSE:
        return PyGameVideoExpose()
    

#---------------------------------------------------------
def instance(): return _manager


__all__ = ['EventManager', 'instance', 'PyGameMessage']